#ifndef MONEY_MARKET_HPP_INCLUDED
#define MONEY_MARKET_HPP_INCLUDED

#include <map>
#include <set>
#include <string>
#include <vector>

#include "citizen_fwd.hpp"
#include "formula_callable.hpp"
#include "government_fwd.hpp"
#include "item_type.hpp"

class money_market : public game_logic::formula_callable {
public:
	struct offer {
		const_item_type_ptr type;
		int quantity;
		int price;
		citizen_ptr trader;

		//the actual item which might be an upgrade of what is being sold
		//in the market.
		std::string actual_item;
	};

	explicit money_market(government_ptr gov);

	void prepare_market();
	void resolve_market();

	void add_buy(const offer& o);
	void add_sell(const offer& o);

	void clear();

	std::string description() const;

	int last_buy_price(const std::string& item) const;
	int last_sell_price(const std::string& item) const;

	//the prices the player can buy/sell goods at at this market.
	int can_buy_at(const const_item_type_ptr& item) const;
	int can_sell_at(const const_item_type_ptr& item) const;

	int last_quantity(const std::string& item) const;
	int last_taxes(const std::string& item) const;

	int last_tax_revenue() const;

	void goods_traded(std::set<const_item_type_ptr>& goods) const;
	const std::vector<offer>& buy_offers(const_item_type_ptr item) const;
	const std::vector<offer>& sell_offers(const_item_type_ptr item) const;

	bool buy_item(const_item_type_ptr item, int price, bool execute=true);
	bool sell_item(const_item_type_ptr item, int price, bool execute=true);

	bool can_buy(const_item_type_ptr i) const;
	bool can_sell(const_item_type_ptr i) const;

	int tax_on_sale(int amount) const;
private:
	bool prepare_buys_sells(std::vector<offer>& buys, std::vector<offer>& sells, int& quantity, int& price, int& tax);
	void resolve_buys_sells(std::vector<offer>& buys, std::vector<offer>& sells);
	variant get_value(const std::string& key) const;
	typedef std::map<const_item_type_ptr, std::vector<offer> > offer_map;
	offer_map buys_, sells_;
	std::map<std::string, int> sell_prices_, buy_prices_;
	std::map<std::string, int> trade_quantities_;
	std::map<std::string, int> trade_taxes_;
	int tax_rate_;
	government_ptr owner_;

	std::set<const_item_type_ptr> cannot_buy_, cannot_sell_;
};

#endif
